﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using System.IO;

namespace JQueryControlToolkit
{
    public static class Extensions
    {
        public static string ToScript(JSObject jsObject)
        {
            StringBuilder sb = new StringBuilder();
            StringWriter writer = new StringWriter(sb);
            jsObject.ToScript(writer);
            return sb.ToString();
        }

        /// <summary>
        /// Takes a string and attempts to parse it into most appropriate Javascript type. For example,
        /// the string "True" becomes true; "1.5" becomes 1.5. If it can't be parsed in an obvious way,
        /// it returns a string in quotes.
        /// </summary>
        /// <param name="paramAsString"></param>
        /// <returns></returns>
        public static string ToJSParam(string paramAsString)
        {
            string cleanParam;

            bool paramIsFunction = paramAsString.StartsWith("function");

            bool paramIsParams = paramAsString.StartsWith("{");

            bool paramAsBool;
            bool paramIsBool = Boolean.TryParse(paramAsString, out paramAsBool);

            int paramAsInt;
            bool paramIsInt = Int32.TryParse(paramAsString, out paramAsInt);

            decimal paramAsDecimal;
            bool paramIsDecimal = Decimal.TryParse(paramAsString, out paramAsDecimal);

            if (paramIsFunction)
            {
                // Function should not have quotes
                cleanParam = paramAsString;
            }
            else if (paramIsParams)
            {
                // Params property list does not require quotes
                cleanParam = paramAsString;
            }
            else if (paramIsInt)
            {
                // Integer does not require quotes
                cleanParam = paramAsString;
            }
            else if (paramIsDecimal)
            {
                // Decimal does not require quotes
                cleanParam = paramAsString;
            }
            else if (paramIsBool)
            {
                // Boolean does not require quotes
                cleanParam = paramAsString.ToLower();
            }
            else
            {
                cleanParam = "\"" + paramAsString + "\"";
            }

            return cleanParam;
        }

        public static string ToSelectorString(SelectorPrefix selectorPrefix)
        {
            string toString = selectorPrefix.ToString();

            if (selectorPrefix == SelectorPrefix.DollarSign)
            {
                toString = "$";
            }
            return toString;
        }

        public static string Indent(int numIndents, string indentString)
        {
            string result = String.Empty;

            for (int i = 0; i < numIndents; i++)
            {
                result += indentString;
            }

            return result;
        }

        public static string Indent(int numIndents)
        {
            return Indent(numIndents, "    ");
        }

        public static string ToScriptBlock(string s)
        {
            string scriptBlock = String.Empty;

            if (!String.IsNullOrEmpty(s))
            {
                scriptBlock = Environment.NewLine +
                    "<script type=\"text/javascript\">" + Environment.NewLine +
                    s + Environment.NewLine +
                    "</script>" + Environment.NewLine;
            }

            return scriptBlock;
        }

        /// <summary>
        /// Removes whitespace (spaces, line breaks and tabs) from beginning and end of a string
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string TrimWhitespace(string s)
        {
            string result = s;

            if (result != null)
            {
                string regexPattern;
                Regex myRegex;

                // End of string
                regexPattern = @"[\r\n\t ]+$";
                myRegex = new Regex(regexPattern);
                result = myRegex.Replace(result, "");

                // Beginning of string
                regexPattern = @"^[\r\n\t ]+";
                myRegex = new Regex(regexPattern);
                result = myRegex.Replace(result, "");
            }

            return result;
        }

        /// <summary>
        /// Replaces all whitespace (tabs, line breaks, spaces) with a single space
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string WhitespaceToSpace(string s)
        {
            string result = TrimWhitespace(s);

            if (result != null)
            {
                string regexPattern;
                Regex myRegex;

                // End of string
                regexPattern = @"[\r\n\t ]+";
                myRegex = new Regex(regexPattern);
                result = myRegex.Replace(result, " ");
            }

            return result;
        }

        public static string ToFunctionExpression(string s)
        {
            return ToFunctionExpression(s, true);
        }

        public static JSFunction ToFunctionExpression(JQuery jquery)
        {
            return new JSFunction(jquery);
        }

        public static string ToFunctionExpression(string s, bool withLineBreaks)
        {
            string result = s;

            if (result != null)
            {
                string lineBreak = String.Empty;
                if (withLineBreaks)
                {
                    lineBreak = Environment.NewLine;
                }

                string indents = String.Empty;
                string closingIndents = String.Empty;

                result = "function() { " + lineBreak + indents + result + " " + lineBreak + closingIndents + "}";
            }

            return result;
        }

        public static string ToParamsExpression(string s)
        {
            string result = s;

            if (result != null)
            {
                result = "{ " + result + " }";
            }

            return result;
        }

        /// <summary>
        /// Ensures that CSS unit such as 25px are passed to jQuery as "25px". jQuery must have non-numeric parameters in quotes.
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string CleanCssParamsList(string s)
        {
            string result = s;

            if (result != null)
            {
                Regex hasAlphaRegex = new Regex(@"[A-Za-z\%\+\-\=]+");

                List<string> cssParamsInput = new List<string>(Extensions.WhitespaceToSpace(result).Split(",".ToCharArray()));
                List<string> cssParamsOutput = new List<string>();

                foreach (string cssParam in cssParamsInput)
                {
                    string[] nameValue = cssParam.Split(":".ToCharArray());
                    bool isValid = nameValue.Length == 2;

                    if (isValid)
                    {
                        string cssParamName = Extensions.TrimWhitespace(nameValue[0]);
                        string cssParamValue = Extensions.TrimWhitespace(nameValue[1]);

                        bool shouldBeQuoted = !cssParamValue.StartsWith("\"") && !cssParamValue.StartsWith("'") && hasAlphaRegex.IsMatch(cssParamValue);
                        if (shouldBeQuoted)
                        {
                            cssParamValue = "\"" + cssParamValue + "\"";
                        }

                        string cssParamOutput = cssParamName + ": " + cssParamValue;
                        cssParamsOutput.Add(cssParamOutput);
                    }
                }

                result = String.Join(", ", cssParamsOutput.ToArray());
            }

            return result;
        }

        // <summary>
        /// Wraps an existing function in $document.ready expression
        /// </summary>
        /// <param name="s"></param>
        /// <returns>String wrapped in $document.ready expression</returns>
        public static string ToDocumentReady(string s)
        {
            string result = "$(document).ready(" +
                s +
                ");" + Environment.NewLine;

            return result;
        }

        public static DomResult ToDocumentReady(JSFunction s)
        {
            return new JQuery("document").CallPlugIn("ready", s);
        }

        public static string ToAjaxPageLoad(string s)
        {
            return "Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(" + s + ");"
                + Environment.NewLine;
        }
    }

    public enum SelectorPrefix
    {
        DollarSign,
        jQuery
    }
}